﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using TimeSheetControl.ObjectModel;
using Microsoft.TeamFoundation.Client;
using Microsoft.VisualStudio.TeamFoundation.WorkItemTracking;

namespace NickHoggard.TimeSheetControl_Reports_VSPackage
{
    public class GroupingTreeViewItem : TreeViewItem
    {
        public string CurrentTFSUser { get; set; }

        public List<TimesheetSummaryItem> TimeSheetSummaryItems { get; set; }
        static void GroupingTreeViewItem_Expanded(object sender, System.Windows.RoutedEventArgs e)
        {
            GroupingTreeViewItem gtvi = sender as GroupingTreeViewItem;
            if (gtvi != null)
            {
                if (gtvi.IsAlreadyPopulated)
                    return;

                switch (gtvi.GroupByType)
                {
                    case GroupBy.Week:
                        BuildTreeNodesByWeek(gtvi, gtvi.TimeSheetSummaryItems);
                        break;
                    case GroupBy.Resource:
                        BuildTreeNodesByResource(gtvi, gtvi.TimeSheetSummaryItems);
                        break;
                    case GroupBy.Day:
                        BuildTreeNodesByDay(gtvi, gtvi.TimeSheetSummaryItems);
                        break;
                    case GroupBy.Project:
                        BuildTreeNodesByProject(gtvi, gtvi.TimeSheetSummaryItems);
                        break;
                    case GroupBy.WorkItem:
                        BuildTreeNodesByWorkItem(gtvi, gtvi.TimeSheetSummaryItems);
                        break;
                    case GroupBy.Iteration:
                        BuildTreeNodesByIteration(gtvi, gtvi.TimeSheetSummaryItems);
                        break;
                    default:
                        throw new NotImplementedException();
                        break;
                }

                gtvi.IsAlreadyPopulated = true;
            }
        }

        public GroupingTreeViewItem(GroupBy groupByType)
            : base()
        {
            this.GroupByType = groupByType;
            this.Header = string.Format("By {0}", System.Enum.GetName(typeof(GroupBy), groupByType));

            this.Expanded += new System.Windows.RoutedEventHandler(GroupingTreeViewItem_Expanded);
            this.Items.Add(new TreeViewItem() { Header="Loading ..." });

        }

        public GroupBy GroupByType { get; set; }
        public enum GroupBy
        {
            Week,
            Day,
            Resource,
            Project,
            WorkItem,
            Iteration
        }


        private void BuildMyWorkThisWeek(TreeViewItem parent, List<TimesheetSummaryItem> summaryItems)
        {
            ////parent.Items.Clear();

            ////System.Globalization.Calendar cal = System.Globalization.CultureInfo.CurrentCulture.Calendar;

            ////var myTasks = from item in summaryItems
            ////            where item.Entry.WeekOfYear == cal.GetWeekOfYear(DateTime.Now, System.Globalization.CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday)
            ////              && item.Entry.TimeSheetDate.Year == DateTime.Now.Year
            ////              && item.Entry.CreatedBy == CurrentTFSUser 
            ////            orderby item.Entry.TimeSheetDate
            ////            group item by new { item.Entry.WeekOfYear } into g
            ////            select new { WeekOfYear = g.Key.WeekOfYear, Hours = g.Sum(b => b.Entry.Hours), Items = g };

            ////CreateGroupingNodes(parent, myTasks.ToList<TimeSheetSummaryItem>());
        }

        private static void BuildTreeNodesByWeek(TreeViewItem parent, List<TimesheetSummaryItem> summaryItems)
        {

            parent.Items.Clear();

            var weeks = from item in summaryItems
                        orderby item.Entry.TimeSheetDate
                        group item by new { item.Entry.WeekOfYear } into g
                        select new { WeekOfYear = g.Key.WeekOfYear, Hours = g.Sum(b => b.Entry.Hours), Items = g };

            foreach (var w in weeks)
            {
                TimesheetTreeViewItem tvi = new TimesheetTreeViewItem()
                {
                    Header = String.Format("Week {0} ({1:f2} hours)", w.WeekOfYear, w.Hours),
                    TimeSheetSummaryItems = w.Items.ToList<TimesheetSummaryItem>()
                };
                parent.Items.Add(tvi);
                CreateGroupingNodes(tvi, tvi.TimeSheetSummaryItems);
            }



        }

        private static void BuildTreeNodesByDay(TreeViewItem parent, List<TimesheetSummaryItem> summaryItems)
        {
            parent.Items.Clear();
            
            var days = from item in summaryItems 
                        orderby item.Entry.DateWithoutTime 
                        group item by new { item.Entry.DateWithoutTime } into g
                        select new { g.Key.DateWithoutTime, Hours = g.Sum(b => b.Entry.Hours), Items = g };

            foreach (var day in days)
            {
                TimesheetTreeViewItem tvi = new TimesheetTreeViewItem()
                {
                    Header = string.Format("{0:dddd} {0:d} ({1:f2} hours)", day.DateWithoutTime, day.Hours),
                    TimeSheetSummaryItems = day.Items.ToList<TimesheetSummaryItem>()
                };
                parent.Items.Add(tvi);
                CreateGroupingNodes(tvi, tvi.TimeSheetSummaryItems);
            }
        }

        private static void BuildTreeNodesByProject(TreeViewItem parent, List<TimesheetSummaryItem> summaryItems)
        {
            parent.Items.Clear();
            var projects = from item in summaryItems
                           group item by new { item.ProjectName } into g
                           select new { g.Key.ProjectName, Hours = g.Sum(b => b.Entry.Hours), Items = g }
                        ;

            foreach (var p in projects)
            {
                TimesheetTreeViewItem tvi = new TimesheetTreeViewItem()
                {
                    Header = String.Format("{0} ({1:f2} hours)", p.ProjectName, p.Hours),
                    TimeSheetSummaryItems = p.Items.ToList<TimesheetSummaryItem>()
                };
                parent.Items.Add(tvi);
                CreateGroupingNodes(tvi, tvi.TimeSheetSummaryItems);
            }
        }

        private static void BuildTreeNodesByWorkItem(TreeViewItem parent, List<TimesheetSummaryItem> summaryItems)
        {
            parent.Items.Clear();
            var workItems = from item in summaryItems
                            group item by new { item.WIID, item.Iteration, item.Title } into g
                            select new { g.Key.WIID, g.Key.Iteration, g.Key.Title, Hours = g.Sum(b => b.Entry.Hours), Items = g };

            foreach (var workItem in workItems)
            {


                TimesheetTreeViewItem tvi = new TimesheetTreeViewItem()
                {
                    Header = string.Format("{0} ({1:f2} hours). {2}", workItem.WIID, workItem.Hours, workItem.Title),
                    ToolTip = string.Format("{0}{1}{2}", workItem.Iteration, Environment.NewLine, workItem.Title),
                    TimeSheetSummaryItems = workItem.Items.ToList<TimesheetSummaryItem>(),
                    Tag = workItem.WIID
                };
                tvi.MouseDoubleClick += new System.Windows.Input.MouseButtonEventHandler(tvi_MouseDoubleClick);
                parent.Items.Add(tvi);
                CreateGroupingNodes(tvi, tvi.TimeSheetSummaryItems);
            }
        }

        private static void BuildTreeNodesByIteration(TreeViewItem parent, List<TimesheetSummaryItem> summaryItems)
        {
            parent.Items.Clear();
            var iterations = from item in summaryItems
                            group item by new { item.Iteration } into g
                            select new { g.Key.Iteration, Hours = g.Sum(b => b.Entry.Hours), Items = g };

            foreach (var i in iterations)
            {
                TimesheetTreeViewItem tvi = new TimesheetTreeViewItem()
                {
                    Header = string.Format("{0} ({1:f2} hours).", i.Iteration, i.Hours),
                    ToolTip = string.Format("{0}", i.Iteration),
                    TimeSheetSummaryItems = i.Items.ToList<TimesheetSummaryItem>()
                };
                parent.Items.Add(tvi);
                CreateGroupingNodes(tvi, tvi.TimeSheetSummaryItems);
            }
        }

        static void tvi_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            try
            {
                TreeViewItem tvi = sender as TreeViewItem;
                if (tvi == null)
                    return;

                int wiid = int.Parse(tvi.Tag.ToString());

                TeamFoundationServer Tfs = TFSTimesheetReportControl.GetCurrentTFSConnection();
                

                DocumentService ServiceDoc = TFSTimesheetReportControl.GetDocumentService();
                IWorkItemDocument OpenWI = ServiceDoc.GetWorkItem(Tfs, wiid, sender);
                OpenWI.Load();
                // Without the Reload() you'll get the WI from Team Explorer's cache
                OpenWI.Reload();
                ServiceDoc.ShowWorkItem(OpenWI);
            }
            catch (Exception ex)
            {
                string exceptionDetails = string.Empty;

#if DEBUG
                exceptionDetails = ex.Message;
#endif

                
                //MessageBox.Show(string.Format("An exception occurred while attempting to open the work item. {0}", exceptionDetails));
            }
        }


        private static void BuildTreeNodesByResource(TreeViewItem parent, List<TimesheetSummaryItem> summaryItems)
        {
            parent.Items.Clear();

            TreeViewItem n1Resources = new TreeViewItem() { Header = "By Resource" };

            var resources = from item in summaryItems
                            group item by new { item.Entry.CreatedBy } into g
                            select new { g.Key.CreatedBy, Hours = g.Sum(b => b.Entry.Hours), Items = g };

            foreach (var r in resources)
            {
                TimesheetTreeViewItem tvi = new TimesheetTreeViewItem() { 
                    Header = String.Format("{0} ({1:f2} hours)", r.CreatedBy, r.Hours),
                    TimeSheetSummaryItems = r.Items.ToList<TimesheetSummaryItem>()
                };
                parent.Items.Add(tvi);
                CreateGroupingNodes(tvi, tvi.TimeSheetSummaryItems);
            }
        }

        private static void CreateGroupingNodes(TreeViewItem parent, List<TimesheetSummaryItem> summaryItems)
        {
            TreeViewItem currentNode = parent;
            List<GroupBy> currentGrouping = new List<GroupBy>();

            while (currentNode != null)
            {
                GroupingTreeViewItem gtvi = currentNode as GroupingTreeViewItem;
                if (gtvi != null)
                    currentGrouping.Add(gtvi.GroupByType);

                currentNode = currentNode.Parent as TreeViewItem;
            }

            if (!currentGrouping.Contains(GroupBy.Week))
            {
                parent.Items.Add(new GroupingTreeViewItem(GroupingTreeViewItem.GroupBy.Week) { TimeSheetSummaryItems = summaryItems });
            }

            // Only allow "By Day" if already filtered to week
            if (!currentGrouping.Contains(GroupBy.Day) && currentGrouping.Contains(GroupBy.Week))
            {
                parent.Items.Add(new GroupingTreeViewItem(GroupingTreeViewItem.GroupBy.Day) { TimeSheetSummaryItems = summaryItems });
            }
            
            if (! currentGrouping.Contains(GroupBy.Project))
            {
                parent.Items.Add(new GroupingTreeViewItem(GroupingTreeViewItem.GroupBy.Project) { TimeSheetSummaryItems = summaryItems });
            }
            if (! currentGrouping.Contains(GroupBy.Resource))
            {
                parent.Items.Add(new GroupingTreeViewItem(GroupingTreeViewItem.GroupBy.Resource) { TimeSheetSummaryItems = summaryItems });
            }
            if (! currentGrouping.Contains(GroupBy.WorkItem))
            {
                parent.Items.Add(new GroupingTreeViewItem(GroupingTreeViewItem.GroupBy.WorkItem) { TimeSheetSummaryItems = summaryItems });
            }

            // Only allow By Iteration if already filtered by project
            if (!currentGrouping.Contains(GroupBy.Iteration) && currentGrouping.Contains(GroupBy.Project))
            {
                parent.Items.Add(new GroupingTreeViewItem(GroupingTreeViewItem.GroupBy.Iteration) { TimeSheetSummaryItems = summaryItems });
            }
            
        }

        public bool IsAlreadyPopulated { get; set; }
    }
}